package ALMySqlCommon.ALMySqlSafeOp;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

import ALBasicCommon.ALBasicCommonFun;
import ALBasicServer.ALServerAsynTask.ALAsynTaskManager;
import ALMySqlCommon.ALMySqlDBConditionObj;
import ALMySqlCommon.ALMySqlCommonObj._IALMySqlBaseDBBO;
import ALMySqlCommon.ALMySqlCommonObj.ALMySqlConnectionPool._AALMySqlBaseDBObj;
import ALMySqlCommon.ALMySqlCommonObj.ALMySqlErrDealer.ALMySqlDefaultErrDealer;
import ALMySqlCommon.ALMySqlCommonObj.ALMySqlErrDealer._IALMySqlDBExeErrorDealer;
import ALMySqlCommon.ALMySqlDBExcutor.ALMySqlDBExcutor;
import ALMySqlCommon.ALMySqlDBExcutor.ALMySqlUpdateValue;
import ALServerLog.ALServerLog;

/*********************
 * 数据库安全操作对象中单个数据库的操作管理对象
 * 此对象对数据和操作队列进行管理
 * 
 * 并负责数据的读取和写入等定期更新处理
 * @author mj
 *
 */
public class _TALMySqlSafeOpDBObj<T extends _AALMySqlBaseDBObj>
{
	//数据库对象
	private T _m_dbObj;
	//执行异步数据库操作任务的线程索引
	private int _m_iAsyncTaskThreadIdx;
	//数据相关的保存位置
	private String _m_sSavePath;
	
	//是否初始化完成
	private boolean _m_bIsInited;
	
	//本数据库的错误处理对象
	private ALMySqlSafeOpErrDealer _m_edErrDealer;
	
	//缓存文件管理器
	private ALMySqlSafeOpDBCacheFile _m_cfCacheFile;
	
	//需要执行的操作队列
	private LinkedList<ALMySqlSafeOpData> _m_lSqlExeQueue;
	//执行语句的操作序列号，保证执行的顺序以及序列号唯一性
	//当前最大的操作序列号
	//注意操作序列号在每次清空操作缓存的时候都将重置为0
	//当缓存没有被全部处理之前，所有的操作错误都将不会被清空
	private AtomicLong _m_lSqlSerialize;
	
	//处理操作的序列号，当操作序列号不同表示已经是不同的处理队列，需要终止处理过程
	private long _m_lDealingSerialize;
	//最后一次开始处理的时间戳，一般10秒之内不建议多次开启处理
	//在数据清空的时候，需要将这个标记重置，以保证下一次添加可以正常开启任务
	private long _m_lLastStartDealingTimeMS;
	
	/**********
	 * 是否强制无错误
	 * 此变量在出现异常情况，导致语句完全无法执行的时候可以通过设置此变量让所有语句得以强制执行
	 */
	private boolean _m_bIsForceNoError;
	/**************
	 * 数据库操作对象的额外处理对象接口
	 */
	private _IALMySqlSafeOpDBExDealer _m_ExDealer;
	
	//锁对象
	private ReentrantLock _m_mutex;

	public _TALMySqlSafeOpDBObj(T _dbObj, int _asyncTaskThreadIdx, String _savePath)
	{
		_m_dbObj = _dbObj;
		_m_iAsyncTaskThreadIdx = _asyncTaskThreadIdx;
		_m_sSavePath = _savePath;
		
		_m_bIsInited = false;
		
		_m_edErrDealer = new ALMySqlSafeOpErrDealer(this);
		
		_m_cfCacheFile = new ALMySqlSafeOpDBCacheFile(this);
		
		_m_lSqlExeQueue = new LinkedList<ALMySqlSafeOpData>();
		_m_lSqlSerialize = new AtomicLong();
		
		_m_lDealingSerialize = 0;
		_m_lLastStartDealingTimeMS = 0;
		
		_m_bIsForceNoError = false;
		
		_m_ExDealer = null;
		
		_m_mutex = new ReentrantLock();
	}
	public _TALMySqlSafeOpDBObj(T _dbObj, int _asyncTaskThreadIdx, String _savePath, _IALMySqlSafeOpDBExDealer _exDealer)
	{
		_m_dbObj = _dbObj;
		_m_iAsyncTaskThreadIdx = _asyncTaskThreadIdx;
		_m_sSavePath = _savePath;
		
		_m_bIsInited = false;
		
		_m_edErrDealer = new ALMySqlSafeOpErrDealer(this);
		
		_m_cfCacheFile = new ALMySqlSafeOpDBCacheFile(this);
		
		_m_lSqlExeQueue = new LinkedList<ALMySqlSafeOpData>();
		_m_lSqlSerialize = new AtomicLong();
		
		_m_lDealingSerialize = 0;
		_m_lLastStartDealingTimeMS = 0;
		
		_m_bIsForceNoError = false;
		
		_m_ExDealer = _exDealer;
		
		_m_mutex = new ReentrantLock();
	}
	public _TALMySqlSafeOpDBObj(T _dbObj, int _asyncTaskThreadIdx, String _savePath, _IALMySqlSafeOpDBExDealer _exDealer, _IALMySqlDBExeErrorDealer _exErrDealer)
	{
		_m_dbObj = _dbObj;
		_m_iAsyncTaskThreadIdx = _asyncTaskThreadIdx;
		_m_sSavePath = _savePath;
		
		_m_bIsInited = false;
		
		_m_edErrDealer = new ALMySqlSafeOpErrDealer(this, _exErrDealer);
		
		_m_cfCacheFile = new ALMySqlSafeOpDBCacheFile(this);
		
		_m_lSqlExeQueue = new LinkedList<ALMySqlSafeOpData>();
		_m_lSqlSerialize = new AtomicLong();
		
		_m_lDealingSerialize = 0;
		_m_lLastStartDealingTimeMS = 0;
		
		_m_bIsForceNoError = false;
		
		_m_ExDealer = _exDealer;
		
		_m_mutex = new ReentrantLock();
	}
	
	protected void _lock() {_m_mutex.lock();}
	protected void _unlock() {_m_mutex.unlock();}
	
	public T getDB() {return _m_dbObj;}
	public int getThreadIdx() {return _m_iAsyncTaskThreadIdx;}
	public String getSavePath() {return _m_sSavePath;}
	public long getDealingSerialize() {return _m_lDealingSerialize;}
	public int getCurQueueCount() {return _m_lSqlExeQueue.size();}
	
	/************
	 * 构造新的操作序列号并返回
	 * 返回的是增加后的值
	 * @return
	 */
	public long _newSerialize() { return _m_lSqlSerialize.incrementAndGet();}
	
	/***************
	 * 设置是否强制执行SQL无错误，可以保证语句全部被执行完毕并清除
	 * @param _isForceNoError
	 */
	public void setIsForceNoError(boolean _isForceNoError)
	{
		_m_bIsForceNoError = _isForceNoError;
		
		//输出操作日志
		ALServerLog.Sys("Set IsForceNoError: " + _m_bIsForceNoError);
	}
	
	/*****************
	 * 获取指定数量的SQL语句字符串
	 * @param _recList
	 * @param _count
	 */
	public void getTopSQL(List<String> _recList, int _count)
	{
		if(null == _recList)
			return ;

		_lock();
		
		try
		{
			ALMySqlSafeOpData tmp = null;
			for(int i = 0; i < _count; i++)
			{
				//超过队列长度直接跳出
				if(i >= _m_lSqlExeQueue.size())
					return ;
				
				tmp = _m_lSqlExeQueue.get(i);
				if(null == tmp)
					continue;
				
				_recList.add(tmp.getQuery());
			}
		}
		finally
		{
			_unlock();
		}
	}
	
	/*********************
	 * 初始化本数据库的相关缓冲处理
	 * @return
	 */
	public boolean init()
	{
		if(_m_bIsInited)
			return false;
		
		_lock();
		
		try
		{
			//先初始化缓存文件相关
			if(!_m_cfCacheFile.init(_m_lSqlExeQueue))
				return false;
			
			//根据队列获取最高的自增Id
			long maxSerialize = 0;
			for(int i = 0; i < _m_lSqlExeQueue.size(); i++)
			{
				if(maxSerialize < _m_lSqlExeQueue.get(i).getSerialize())
					maxSerialize = _m_lSqlExeQueue.get(i).getSerialize();
			}
			
			//设置当前的序列号为下一个
			_m_lSqlSerialize.set(maxSerialize);
			
			//判断是否没有数据，如果没有任何数据，则在初始化的时候将缓存文件清空
			_checkEmptyDataAndClear();
			
			//设置初始化完成
			_m_bIsInited = true;

			//在安全处理初始化的时候，将所有缓存处理都执行完。保证数据库恢复到最新状态
			//注意这里返回的是是否还需要继续处理，如果返回true则表示有问题
			if(_async_DealQueryOp(_m_lDealingSerialize))
			{
				ALServerLog.Error("Init Safe DBOp, deal AllCacheQuery Fail!");
				return false;
			}
			
			return true;
		}
		finally
		{
			_unlock();
		}
	}
	
	/*****************
	 * 尝试开始本管理器的操作队列操作
	 */
	public void tryStartOp()
	{
		//判断是否已经初始化，如果未进行初始化则不允许进行数据库操作
		if(!_m_bIsInited)
		{
			ALServerLog.Error("Add Query when DB is not inited!");
			return ;
		}
		
		_lock();
		
		try
		{
			//队列为空则不处理
			if(_m_lSqlExeQueue.isEmpty())
				return ;
			
			//判断是否当前时间已经超过需要开启执行任务的时间
			//超过则开启，如未操作则不开启执行任务
			if(_m_lLastStartDealingTimeMS != 0 && _m_lLastStartDealingTimeMS - ALBasicCommonFun.getNowTimeMS() < 10000)
			{
				//此时未超过时间，不开启执行任务
				return ;
			}
			
			//累加操作序列号
			_m_lDealingSerialize++;
			//开启任务执行
			ALAsynTaskManager.getInstance().regTask(_m_iAsyncTaskThreadIdx, new ALAsyncMySqlSafeOpDealTask(this, _m_lDealingSerialize));
		}
		finally
		{
			_unlock();
		}
	}
	
	/****************
	 * 在重试执行缓存语句的时候调用的事件函数，此处将调用外部接口对象进行相关处理
	 * @param _retryCount
	 */
	public void onRetryDealQuery(int _retryCount)
	{
		if(null != _m_ExDealer)
		{
			_m_ExDealer.onRetryQueryOpCountWarning(_retryCount);
		}
	}
	
	/*********************
	 * 实际处理缓存数据的处理，带入的是处理序列号
	 * 注意本函数需要在异步线程中处理，避免卡住主逻辑线程池
	 * 
	 * 同时由于本处理是将所有缓存写入，因此会直接将所有数据处理完毕
	 * 不会逐个处理，避免在逐个处理过程中有其他行为可能引起处理问题
	 * @param _dealingSerialize
	 * @return 返回是否成功执行所有操作
	 */
	public boolean _async_DealQueryOp(long _dealingSerialize)
	{
		_lock();
		
		try
		{
			//判断序列号是否一致，不一致则不处理
			if(_m_lDealingSerialize != _dealingSerialize)
				return false;
			
			//输出日志，表示开始处理
			ALServerLog.Sys("Start Deal DB: " + _m_dbObj.getDBName() + " Safe Op Query! Count: [" + _m_lSqlExeQueue.size() + "] Time: " + ALBasicCommonFun.getNowTimeMS());
			
			//统计总共处理的数据数量
			int dealSucCount = 0;
			//统计处理失败的数量，此处统计的为不影响继续执行的非必要错误数量
			int dealFailCount = 0;

			//是否继续处理
			boolean isContinue = true;
			//第一个需要处理的数据序列号
			long curDealingSerialize = 0;
			
			try
			{
				//在可循环的情况下进行循环，且需要保证队列有数据
				while(isContinue && !_m_lSqlExeQueue.isEmpty())
				{
					//取出一个数据进行操作
					ALMySqlSafeOpData data = _m_lSqlExeQueue.getFirst();
					//设置当前需要处理的序列号
					curDealingSerialize = data.getSerialize();
					
					//解锁数据，在数据库执行过程希望不要卡死其他线程，因此这里需要解锁处理
					_unlock();
					
					//进行处理
					if(null != data)
					{
						//处理数据操作
						EALMySqlSafeOpErr opRes = data.execSQL(_m_dbObj);
						//根据操作的结果进行后续的判断和处理
						switch (opRes) {
						case CONN_ERR:
							//连接错误，此时需要断开处理
							isContinue = false;
							break;
						case NONE:
							//正确处理，增加成功处理数量
							dealSucCount++;
							break;
						case SYNTAX_ERR:
							//增加报错数量
							dealFailCount++;
							break;
						case DATA_ERR:
							//增加报错数量
							dealFailCount++;
							break;
						case OTHER_ERR:
							//增加报错数量
							dealFailCount++;
							break;
						default:
							//一般不会到这里，到的情况输出一个报错
							ALServerLog.Error("Err Res for Mysql SafeOp: " + opRes);
							//默认按照无错误处理
							dealSucCount++;
							break;
						}
					}
					
					//继续加锁，保证逻辑正常的情况下，在对队列进行判断和处理的时候是加锁的
					_lock();
					
					//根据是否继续进行不同的处理，如果不继续表示数据未处理成功，不允许从列表中删除
					if(!isContinue && !_m_bIsForceNoError)
						break;
					
					//由于可能有特殊变量干预逻辑，所以这里将continue强制设置为true
					isContinue = true;
					//从队列删除第一个数据
					_m_lSqlExeQueue.removeFirst();
				}
			}
			finally
			{
				//保存当前处理数据的序列号
				_m_cfCacheFile.setCurDealingSerialize(curDealingSerialize);
				
				//输出日志，表示处理结束
				if(isContinue)
				{
					ALServerLog.Sys("Suc Deal DB: " + _m_dbObj.getDBName() + " Safe Op Query!\n"
							+ "SucCount: [" + dealSucCount + "]\n"
							+ "FailCount: [" + dealFailCount + "]\n"
							+ "Query Left Count [" + _m_lSqlExeQueue.size() + "]");

					//对剩余数据进行判断，如果无剩余数据则可以清除所有cache及相关数据
					_checkEmptyDataAndClear();
				}
				else
				{
					ALServerLog.Sys("Error Break Deal DB: " + _m_dbObj.getDBName() + " Safe Op Query!\n"
							+ "SucCount: [" + dealSucCount + "]\n"
							+ "FailCount: [" + dealFailCount + "]\n"
							+ "Query Left Count [" + _m_lSqlExeQueue.size() + "]");
				}
			}
			
			//返回是否继续，只有当不继续的时候表示执行错误，此时外部需要延迟执行本任务确保所有语句能定期执行
			return !isContinue;
		}
		finally
		{
			_unlock();
		}
	}
	
	/***************
	 * 添加操作的语句
	 * @param _query
	 * @param _byteList
	 */
	public void addDealQuery(String _query, ArrayList<byte[]> _byteList)
	{
		//判断是否已经初始化，如果未进行初始化则不允许进行数据库操作
		if(!_m_bIsInited)
		{
			ALServerLog.Error("Add Query when DB is not inited!");
			return ;
		}
		
		int cacheCount = 0;
		
		_lock();
		
		try
		{
			//构造数据对象放入队列结尾
			ALMySqlSafeOpData data = new ALMySqlSafeOpData(_newSerialize(), _query, _byteList, ALBasicCommonFun.getNowTimeMS());
			//加入队列
			_m_lSqlExeQueue.addLast(data);
			//获取缓存数量
			cacheCount = _m_lSqlExeQueue.size();
			
			//向缓存文件写入
			if(null != _m_cfCacheFile)
				_m_cfCacheFile.appendData(data);
		}
		finally
		{
			_unlock();
			
			//缓存数量处理
			if(null == _m_ExDealer)
			{
				//无指定处理对象才会整百报警
				if(cacheCount % 100 == 0)
				{
					ALServerLog.Warning("DB: " + getDB().getDBName() + " Got Sql[Count: " + cacheCount + "] Need to be executed!");
				}
			}
			else
			{
				_m_ExDealer.onQueryCacheCountWarning(cacheCount);
			}
			
			//尝试开启补偿操作
			tryStartOp();
		}
	}
	
	/******************
	 * 检查是否空数据，是则需要清除缓存及本数据
	 * @return 返回数据是否为空
	 */
	protected boolean _checkEmptyDataAndClear()
	{
		//对剩余数据进行判断，如果无剩余数据则可以清除所有cache及相关数据
		_lock();
		
		try
		{
			//判断是否没有数据，如果没有任何数据，则在初始化的时候将缓存文件清空
			if(_m_lSqlExeQueue.isEmpty())
			{
				//清空缓存文件
				_m_cfCacheFile.resetAllFile(0);
				
				//重置序列号
				_m_lSqlSerialize.set(0);
				
				//重置处理任务开启的时间，这样在下一次添加数据的时候可以立即开始执行任务
				_m_lLastStartDealingTimeMS = 0;
				
				//保存当前处理数据的序列号为0
				_m_cfCacheFile.setCurDealingSerialize(0);
				
				return true;
			}
			
			return false;
		}
		finally
		{
			_unlock();
		}
	}
	
	
	/*****************
	 * ========================== 数据库对外的操作函数
	 */

    /**
     * 插入BO对象函数
     */
    public boolean InsertBO(_IALMySqlBaseDBBO _bo)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				String insertSQL = ALMySqlDBExcutor.GetInsertSql(_bo);
				addDealQuery(insertSQL, null);
				//输出日志
				ALServerLog.Error("Insert DB on ErrCache Didn't all clear! " + insertSQL);
				
				return false;
			}
		}
		finally
		{
			_unlock();
		}
    	
    	return ALMySqlDBExcutor.InsertBO(_m_dbObj, _bo, _m_edErrDealer);
    }
    public boolean DirectInsertBO(_IALMySqlBaseDBBO _bo)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.InsertBO(_m_dbObj, _bo, ALMySqlDefaultErrDealer.G_instance);
    }

    public boolean InsertBO(_IALMySqlBaseDBBO _bo, ArrayList<byte[]> _binaryList)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				String insertSQL = ALMySqlDBExcutor.GetInsertSql(_bo);
				addDealQuery(insertSQL, _binaryList);
				//输出日志
				ALServerLog.Error("Insert DB on ErrCache Didn't all clear! " + insertSQL);
				
				return false;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.InsertBO(_m_dbObj, _bo, _binaryList, _m_edErrDealer);
    }
    public boolean DirectInsertBO(_IALMySqlBaseDBBO _bo, ArrayList<byte[]> _binaryList)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.InsertBO(_m_dbObj, _bo, _binaryList, ALMySqlDefaultErrDealer.G_instance);
    }

    public int ReplaceBO(_IALMySqlBaseDBBO _bo)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				String replaceSQL = ALMySqlDBExcutor.GetReplaceSql(_bo);
				addDealQuery(replaceSQL, null);
				//输出日志
				ALServerLog.Error("Replace DB on ErrCache Didn't all clear! " + replaceSQL);
				
				return 0;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.ReplaceBO(_m_dbObj, _bo, _m_edErrDealer);
    }
    public int DirectReplaceBO(_IALMySqlBaseDBBO _bo)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.ReplaceBO(_m_dbObj, _bo, ALMySqlDefaultErrDealer.G_instance);
    }

    /*********************
     * 根据条件获取对应的数据对象的数量
     * 
     * @author alzq.z
     * @time   Jan 13, 2014 11:59:18 PM
     */
    public long getCountByCondition(ALMySqlDBConditionObj _conditionObj, _IALMySqlBaseDBBO _bo)
    {
    	return ALMySqlDBExcutor.getCountByCondition(_m_dbObj, _conditionObj, _bo);
    }
    public long getCountByCondition(ALMySqlDBConditionObj _conditionObj, _IALMySqlBaseDBBO _bo, _IALMySqlDBExeErrorDealer _errDealer)
    {
    	return ALMySqlDBExcutor.getCountByCondition(_m_dbObj, _conditionObj, _bo, _errDealer);
    }

    /*********************
     * 根据条件获取对应的数据对象队列
     * 
     * @author alzq.z
     * @time   Jan 13, 2014 11:59:18 PM
     */
    @SuppressWarnings({ "rawtypes" })
    public List getListByCondition(ALMySqlDBConditionObj _conditionObj, _IALMySqlBaseDBBO _bo)
    {
    	return ALMySqlDBExcutor.getListByCondition(_m_dbObj, _conditionObj, _bo);
    }
    @SuppressWarnings({ "rawtypes" })
    public List getListByCondition(ALMySqlDBConditionObj _conditionObj, _IALMySqlBaseDBBO _bo, _IALMySqlDBExeErrorDealer _errDealer)
    {
    	return ALMySqlDBExcutor.getListByCondition(_m_dbObj, _conditionObj, _bo, _errDealer);
    }

    /**
     * 根据Condition进行UPDATE
     * 
     * @param condition
     * @param firstLine
     * @param endLine
     * @return
     * @throws Exception
     */
    public int updateByCondition(ALMySqlDBConditionObj _conditionObj, ALMySqlUpdateValue _updateValue)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				String updateSQL = ALMySqlDBExcutor.GetUpdateSql(_conditionObj, _updateValue.getSetStr());
				addDealQuery(updateSQL, null);
				//输出日志
				ALServerLog.Error("Update DB on ErrCache Didn't all clear! " + updateSQL);
				
				return 0;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.updateByCondition(_m_dbObj, _conditionObj, _updateValue, _m_edErrDealer);
    }
    public int DirectUpdateByCondition(ALMySqlDBConditionObj _conditionObj, ALMySqlUpdateValue _updateValue)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.updateByCondition(_m_dbObj, _conditionObj, _updateValue, ALMySqlDefaultErrDealer.G_instance);
    }
    
    public int updateByCondition(ALMySqlDBConditionObj _conditionObj, String _updateStr)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				String updateSQL = ALMySqlDBExcutor.GetUpdateSql(_conditionObj, _updateStr);
				addDealQuery(updateSQL, null);
				//输出日志
				ALServerLog.Error("Update DB on ErrCache Didn't all clear! " + updateSQL);
				
				return 0;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.updateByCondition(_m_dbObj, _conditionObj, _updateStr, _m_edErrDealer);
    }
    public int DirectUpdateByCondition(ALMySqlDBConditionObj _conditionObj, String _updateStr)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.updateByCondition(_m_dbObj, _conditionObj, _updateStr, ALMySqlDefaultErrDealer.G_instance);
    }

    public int updateByCondition(ALMySqlDBConditionObj _conditionObj, String _updateStr, ArrayList<byte[]> _binaryList)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				String updateSQL = ALMySqlDBExcutor.GetUpdateSql(_conditionObj, _updateStr);
				addDealQuery(updateSQL, _binaryList);
				//输出日志
				ALServerLog.Error("Update DB on ErrCache Didn't all clear! " + updateSQL);
				
				return 0;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.updateByCondition(_m_dbObj, _conditionObj, _updateStr, _binaryList, _m_edErrDealer);
    }
    public int DirectUpdateByCondition(ALMySqlDBConditionObj _conditionObj, String _updateStr, ArrayList<byte[]> _binaryList)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.updateByCondition(_m_dbObj, _conditionObj, _updateStr, _binaryList, ALMySqlDefaultErrDealer.G_instance);
    }

    /**
     * 根据Condition进行delete
     * 
     * @param condition
     * @param firstLine
     * @param endLine
     * @return
     * @throws Exception
     */
    public int delByCondition(ALMySqlDBConditionObj _conditionObj)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				String delSQL = "delete " + _conditionObj.getConditionAndTables() + ";";
				addDealQuery(delSQL, null);
				//输出日志
				ALServerLog.Error("Delete DB on ErrCache Didn't all clear! " + delSQL);
				
				return 0;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.delByCondition(_m_dbObj, _conditionObj, _m_edErrDealer);
    }
    public int DirectDelByCondition(ALMySqlDBConditionObj _conditionObj)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.delByCondition(_m_dbObj, _conditionObj, ALMySqlDefaultErrDealer.G_instance);
    }

    /*********************
     * 判断对应的表是否存在
     * 
     * @author alzq.z
     * @time   Jan 13, 2014 11:59:18 PM
     */
    public boolean isTableExist(String _tableName)
    {
    	return ALMySqlDBExcutor.isTableExist(_m_dbObj, _tableName);
    }
    public boolean isTableExist(String _tableName, _IALMySqlDBExeErrorDealer _errDealer)
    {
    	return ALMySqlDBExcutor.isTableExist(_m_dbObj, _tableName, _errDealer);
    }
    

    public boolean execute(String sql)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				addDealQuery(sql, null);
				//输出日志
				ALServerLog.Error("Delete DB on ErrCache Didn't all clear! " + sql);
				
				return false;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.execute(sql, _m_dbObj, _m_edErrDealer);
    }
    public boolean DirectExecute(String sql)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.execute(sql, _m_dbObj, ALMySqlDefaultErrDealer.G_instance);
    }
    
    /***********************
     * do some sql operation<br>
     * and return the count of the data have been operate<br>
     * 
     * @param sql
     * @param dbHost
     * @param dbName
     * @param dbUser
     * @param dbPass
     * @return
     * @throws SQLException
     */
    public int executeUpdate(String sql)
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				addDealQuery(sql, null);
				//输出日志
				ALServerLog.Error("Update DB on ErrCache Didn't all clear! " + sql);
				
				return 0;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.executeUpdate(sql, _m_dbObj, _m_edErrDealer);
    }
    public int DirectExecuteUpdate(String sql)
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.executeUpdate(sql, _m_dbObj, ALMySqlDefaultErrDealer.G_instance);
    }

    public int executeInsert(String sql)
            throws SQLException
    {
    	//判断是否有错误数据未处理完，有则直接调用失败处理
		_lock();
		
		try
		{
			//队列为空则不处理
			if(!_m_lSqlExeQueue.isEmpty())
			{
				//此时由于数据不为空，直接按照失败进行处理
				addDealQuery(sql, null);
				//输出日志
				ALServerLog.Error("Insert DB on ErrCache Didn't all clear! " + sql);
				
				return 0;
			}
		}
		finally
		{
			_unlock();
		}
		
    	return ALMySqlDBExcutor.executeInsert(sql, _m_dbObj, _m_edErrDealer);
    }
    public int DirectExecuteInsert(String sql)
            throws SQLException
    {
    	//直接执行的逻辑不做错误处理，按特殊流程走
    	return ALMySqlDBExcutor.executeInsert(sql, _m_dbObj, ALMySqlDefaultErrDealer.G_instance);
    }
    
    /**
     * 获取ID列表集合
     * @param sql
     * @param connectionInfo
     * @return
     */
    public List<Integer> getFirstNumList(String sql)
    {
    	return ALMySqlDBExcutor.getFirstNumList(sql, _m_dbObj);
    }
    public List<Integer> getFirstNumList(String sql, _IALMySqlDBExeErrorDealer _errDealer)
    {
    	return ALMySqlDBExcutor.getFirstNumList(sql, _m_dbObj, _errDealer);
    }

    @SuppressWarnings("rawtypes")
    public List executeQuery(String _sql, _IALMySqlBaseDBBO _bo)
    {
    	return ALMySqlDBExcutor.executeQuery(_sql, _m_dbObj, _bo);
    }
    @SuppressWarnings("rawtypes")
    public List executeQuery(String _sql, _IALMySqlBaseDBBO _bo, _IALMySqlDBExeErrorDealer _errDealer)
    {
    	return ALMySqlDBExcutor.executeQuery(_sql, _m_dbObj, _bo, _errDealer);
    }

    public void setUTF8()
    {
    	ALMySqlDBExcutor.setUTF8(_m_dbObj);
    }
    public void setUTF8(_IALMySqlDBExeErrorDealer _errDealer)
    {
    	ALMySqlDBExcutor.setUTF8(_m_dbObj, _errDealer);
    }
}
